package services

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"strings"

	"jlpay-sdk-go/pkg/jlpay/core"
	"jlpay-sdk-go/pkg/jlpay/models"
	"jlpay-sdk-go/pkg/jlpay/utils"
)

// FileService 文件上传服务类 - 独立的文件传输服务
type FileService struct {
	config       *core.Config
	httpClient   core.HttpClient
	signVerifier core.SignVerifier
	cryptoSvc    core.CryptoService
}

// NewFileService 创建文件服务
func NewFileService(config *core.Config) *FileService {
	return &FileService{
		config:       config,
		httpClient:   core.NewDefaultHttpClient(config.ConnectTimeout, config.ReadTimeout),
		signVerifier: core.NewDefaultSignVerifier(config),
		cryptoSvc:    core.NewDefaultCryptoService(config),
	}
}

// getAPIURL 获取API URL
func (s *FileService) getAPIURL(request interface{}) string {
	// 尝试使用GetAPIURI方法
	if uriGetter, ok := request.(interface{ GetAPIURI() string }); ok {
		return s.config.BaseURL + uriGetter.GetAPIURI()
	}
	
	// 默认路径
	return s.config.BaseURL + "/open/file/upload"
}

// Post 发送文件上传POST请求
func (s *FileService) Post(request interface{}, responseClass interface{}) error {
	// 检查请求参数
	if checker, ok := request.(interface{ CheckRequiredParams(*core.Config) error }); ok {
		if err := checker.CheckRequiredParams(s.config); err != nil {
			return fmt.Errorf("参数校验失败: %w", err)
		}
	}

	// 构建完整URL
	url := s.getAPIURL(request)
	utils.Debugf("文件上传请求URL: %s", url)

	// 获取URI部分用于签名
	uri := strings.TrimPrefix(url, s.config.BaseURL)

	// 准备multipart数据
	var body bytes.Buffer
	writer := multipart.NewWriter(&body)
	
	// 添加meta字段（如果存在）
	var metaForSign string
	if metaRequest, ok := request.(interface{ GetMeta() string }); ok {
		meta := metaRequest.GetMeta()
		if meta != "" {
			metaForSign = meta
			if err := writer.WriteField("meta", meta); err != nil {
				return fmt.Errorf("写入meta字段失败: %w", err)
			}
		}
	}
	
	// 添加文件字段
	if fileRequest, ok := request.(interface{ 
		GetFile() io.Reader
		GetFileName() string 
	}); ok {
		fileName := fileRequest.GetFileName()
		if fileName == "" {
			fileName = "upload_file"
		}
		
		part, err := writer.CreateFormFile("file", fileName)
		if err != nil {
			return fmt.Errorf("创建文件字段失败: %w", err)
		}
		
		fileReader := fileRequest.GetFile()
		if _, err := io.Copy(part, fileReader); err != nil {
			return fmt.Errorf("写入文件内容失败: %w", err)
		}
	} else if fileRequest, ok := request.(interface{ GetFile() io.Reader }); ok {
		// 处理没有GetFileName方法的情况
		part, err := writer.CreateFormFile("file", "upload_file")
		if err != nil {
			return fmt.Errorf("创建文件字段失败: %w", err)
		}
		
		fileReader := fileRequest.GetFile()
		if _, err := io.Copy(part, fileReader); err != nil {
			return fmt.Errorf("写入文件内容失败: %w", err)
		}
	}
	
	if err := writer.Close(); err != nil {
		return fmt.Errorf("关闭multipart writer失败: %w", err)
	}

	// 使用meta进行签名（而不是body）
	if metaForSign == "" {
		metaForSign = "{}"
	}
	
	utils.Debugf("即将签名的meta字符串: %s", metaForSign)
	utils.Debugf("meta字符串类型: %T", metaForSign)
	utils.Debugf("meta字符串长度: %d", len(metaForSign))
	
	sign, timestamp, nonce, err := s.signVerifier.Sign("POST", uri, metaForSign)
	if err != nil {
		return fmt.Errorf("签名失败: %w", err)
	}

	// 添加认证和签名头
	headers := map[string]string{
		"Content-Type":      writer.FormDataContentType(),
		"x-jlpay-appid":     s.config.AppID,
		"x-jlpay-nonce":     nonce,
		"x-jlpay-timestamp": timestamp,
		"x-jlpay-sign-alg":  "SM3WithSM2WithDer",
		"x-jlpay-sign":      sign,
	}

	utils.Debugf("=== 文件上传请求信息 ===")
	utils.Debugf("请求URL: %s", url)
	utils.Debugf("请求方法: POST")
	utils.Debugf("请求头:")
	for key, value := range headers {
		utils.Debugf("  %s: %s", key, value)
	}
	utils.Debugf("Meta数据: %s", metaForSign)
	utils.Debugf("=========================")

	// 创建HTTP请求
	req, err := http.NewRequest("POST", url, &body)
	if err != nil {
		return fmt.Errorf("创建HTTP请求失败: %w", err)
	}

	// 设置请求头
	for key, value := range headers {
		req.Header.Set(key, value)
	}

	// 创建HTTP客户端并发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("发送HTTP请求失败: %w", err)
	}
	defer resp.Body.Close()

	// 读取响应
	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("读取响应失败: %w", err)
	}

	utils.Debugf("文件上传响应: %s", string(responseBody))

	// 验证响应签名
	if signature := resp.Header.Get("x-jlpay-sign"); signature != "" {
		if err := s.signVerifier.Verify(
			"POST",
			uri,
			resp.Header.Get("x-jlpay-timestamp"),
			resp.Header.Get("x-jlpay-nonce"),
			string(responseBody),
			signature,
		); err != nil {
			return fmt.Errorf("验证响应签名失败: %w", err)
		}
	}

	// 解析响应
	var responseData map[string]interface{}
	if err := json.Unmarshal(responseBody, &responseData); err != nil {
		return fmt.Errorf("解析响应JSON失败: %w", err)
	}

	// 将响应数据映射到响应对象
	if err := models.ParseResponse(responseData, responseClass); err != nil {
		return fmt.Errorf("解析响应对象失败: %w", err)
	}

	return nil
}

// UploadImage 上传图片
func (s *FileService) UploadImage(request *models.ImageUploadRequest) (*models.FileUploadResponse, error) {
	response := &models.FileUploadResponse{}
	if err := s.Post(request, response); err != nil {
		return nil, err
	}
	return response, nil
}

// UploadVideo 上传视频
func (s *FileService) UploadVideo(request *models.VideoUploadRequest) (*models.FileUploadResponse, error) {
	response := &models.FileUploadResponse{}
	if err := s.Post(request, response); err != nil {
		return nil, err
	}
	return response, nil
}

// UploadPdf 上传PDF
func (s *FileService) UploadPdf(request *models.PdfUploadRequest) (*models.FileUploadResponse, error) {
	response := &models.FileUploadResponse{}
	if err := s.Post(request, response); err != nil {
		return nil, err
	}
	return response, nil
} 